using System;
using System.Collections.Generic;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;

namespace Core
{
	public class CommandRegistrar
	{
	    private readonly string _prefix;
		private readonly Commands2 _commands;
		private readonly CommandBar _commandBar;
		private readonly AddIn _addIn;
		private readonly Dictionary<string, BindableCommandFeature> _features = new Dictionary<string, BindableCommandFeature>();

		public CommandRegistrar(string prefix, Commands2 commands, CommandBar commandBar, AddIn addIn)
		{
		    _prefix = prefix;
			_commands = commands;
			_commandBar = commandBar;
			_addIn = addIn;
		}

	    public string Prefix
	    {
            get { return _prefix; }
	    }

        public void Register(BindableCommandFeature feature)
		{
			string commandName = feature.Name.Replace(" ", "");

			AddCommand(feature.Name, feature.Name.Replace(" ", ""), feature.Binding);

			_features.Add(commandName, feature);
		}

		private void AddCommand(string friendlyName, string commandName, string binding)
		{
			try
			{
				_commands.Item(_prefix + commandName, -1);
				return;
			}
			catch (ArgumentException)
			{
			}

			var guids = new object[] {};
			const int flags = (int) (vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled);

			Command command = _commands.AddNamedCommand(_addIn, commandName, friendlyName, friendlyName, true, 0, ref guids, flags);

			command.AddControl(_commandBar, _commandBar.Controls.Count + 1);
			command.Bindings = binding;
		}

		public bool Exec(string commandName)
		{
			if (!_features.ContainsKey(commandName))
				return false;

			_features[commandName].OnExecute();

			return true;
		}

		public vsCommandStatus QueryStatus(string commandName)
		{
			if (!_features.ContainsKey(commandName))
				return vsCommandStatus.vsCommandStatusUnsupported;

			vsCommandStatus status = vsCommandStatus.vsCommandStatusSupported;

			if (_features[commandName].IsAvailable)
				status |= vsCommandStatus.vsCommandStatusEnabled;

			if (_features[commandName].IsChecked)
				status |= vsCommandStatus.vsCommandStatusLatched;

			return status;
		}
	}
}